import multiply_sim::*;

module booth2_mix (
		   output logic [31:0] o_result,
		   input logic [15:0]  i_a, // multiplicand
		   input logic [15:0]  i_b, // multiplier
		   input logic 	       i_sign, // 0:unsigned, 1:signed
		   input logic 	       i_mode8 // 0:16x16, 1:two 8x8
		   );
   wire 			       a_sign = i_sign & i_a[15];
   wire 			       b_sign = i_sign & i_b[15];
   wire 			       mode8 = i_mode8;
   
   wire [15+1:0] 		       a = {a_sign, i_a};
   wire [15+2:0] 		       b = {{2{b_sign}}, i_b};
   
   // wire 			       a_16_sign = a_sign;
   // wire 			       a_8_L_sign = i_sign & i_a[7];
   // wire 			       a_8_H_sign = i_sign & i_a[15];

   wire 			       b_16_sign = b_sign;
   wire 			       b_8_L_sign = i_sign & i_b[7];
   wire 			       b_8_H_sign = i_sign & i_b[15];
   ////////////////////

   

   wire [15+1:0] 		       a_16 = a;
   wire [7+1:0] 		       a_8_L = {a_8_L_sign, i_a[7:0]};
   wire [7+1:0] 		       a_8_H = {a_8_H_sign, i_a[15:8]};

   
   // wire 			       a_mix_sign_0 = mode8 ? a_8_L_sign : a_16_sign; // for the low 8 bit num when in mode8
   // wire 			       a_mix_sign_1 = mode8 ? a_8_H_sign : a_16_sign;

   
   // good, not change
   //wire [15+2:0] 		       b = {{2{i_sign & i_b[15]}}, i_b[15:0]};
   wire [15+3:0] 		       b_16_ext = {b, 1'b0};
   wire [15+3:0] 		       b_8_L_ext = {b[17:8], b[7:0], 1'b0};
   wire [15+3:0] 		       b_8_H_ext = {b[17:8], 1'b0, b[6:0], 1'b0};
   wire [15+3:0] 		       b_mix_ext_0 = mode8 ? b_8_L_ext : b_16_ext;
   wire [15+3:0] 		       b_mix_ext_1 = mode8 ? b_8_H_ext : b_16_ext;
   //////////////////////////////
   
   
   // wire [15+1:0] 		       a_mix_16 = a[16:0];
   // wire [15+1:0] 		       a_mix_8_L = ;
   // wire [15+1:0] 		       a_mix_8_H = {a[16:8], 1'b0, a[6:0]}; // only one bit are diff with a_mix_16

   
   wire [15+1:0] 		       a_mix_0 = mode8 ? {a_8_L_sign,   a[15:9], a_8_L_sign,    a[7:0]} : a[16:0]; // contain the sign bit, //FIXME:the a[15:9] is no useful when in 8x8 mode
   wire [15+1:0] 		       a_mix_1 = mode8 ? {a_8_H_sign,	a[15:8], 1'b0,		a[6:0]} : a[16:0]; // only one bit are diff with a_mix_16  //FIXME: a[6:0] not useful in 8x8
   




   // PPs for common
   // for common
   logic [15+1:0] 		       pp[8:0]; // total 9 PPs			// FIXME: pp[width/2:0]  // width/2+1
   //logic 			       S[8:0];  // the last one is not needed (must be 0)
   //logic 			       E[8:0];  // the last one is not needed
   logic 			       S[7:0]; // one less than the num of PPs
   logic 			       E[7:0];
   
   // ==================== generate PPs, S and E for any mode ====================
   
   // the low 4 PPs
   booth2_pp_gen #(16+1) mul_pp0
     (
      .pp_out(pp[0]),
      .pp_s(S[0]),
      .pp_e(E[0]),
      .mcand(a_mix_0),		// multiplicand
      .booth2(b_mix_ext_0[2:0])
      );
   
   booth2_pp_gen #(16+1) mul_pp1
     (
      .pp_out(pp[1]),
      .pp_s(S[1]),
      .pp_e(E[1]),
      .mcand(a_mix_0),
      .booth2(b_mix_ext_0[4:2])
      );

   booth2_pp_gen #(16+1) mul_pp2
     (
      .pp_out(pp[2]),
      .pp_s(S[2]),
      .pp_e(E[2]),
      .mcand(a_mix_0),
      .booth2(b_mix_ext_0[6:4])
      );

   booth2_pp_gen #(16+1) mul_pp3
     (
      .pp_out(pp[3]),
      .pp_s(S[3]),
      .pp_e(E[3]),
      .mcand(a_mix_0),
      .booth2(b_mix_ext_0[8:6])
      );


   //the high 5 PPs
   booth2_pp_gen #(16+1) mul_pp4
     (
      .pp_out(pp[4]),
      .pp_s(S[4]),
      .pp_e(E[4]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[10:8])
      );


   booth2_pp_gen #(16+1) mul_pp5
     (
      .pp_out(pp[5]),
      .pp_s(S[5]),
      .pp_e(E[5]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[12:10])
      );

   booth2_pp_gen #(16+1) mul_pp6
     (
      .pp_out(pp[6]),
      .pp_s(S[6]),
      .pp_e(E[6]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[14:12])
      );

   booth2_pp_gen #(16+1) mul_pp7
     (
      .pp_out(pp[7]),
      .pp_s(S[7]),
      .pp_e(E[7]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[16:14])
      );

   
   booth2_pp_gen #(16+1) mul_pp8
     (
      .pp_out(pp[8]),
      .pp_s(),			// the last one is not need (the last PP is 0 or positive, never negative)
      .pp_e(),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[18:16])
      );

   // ==================== the PPs, S and E for 16x16 mode ====================
   logic [15+1:0] 		       pp_16[8:0];	// PPs for 16-bit mode
   logic 			       S_16[7:0];
   logic 			       E_16[7:0];
   
   generate
      genvar 			       i;
      for(i=0;i<=8;i++)
   	begin : mul_pps_16
	   assign pp_16[i] = pp[i];
	end
   endgenerate
   
   generate
      //      genvar 			       i;
      for(i=0;i<=7;i++)
   	begin : mul_SE_16
	   assign S_16[i] = S[i];
	   assign E_16[i] = E[i];
	end
   endgenerate
   
    
   // ==================== the PPs, S and E for 8x8 mode ====================
   logic [7+1:0] 		       pp_8_L[4:0];	//5 PPs for 8-bit mode (high 8 bits)
   logic [7+1:0] 		       pp_8_H[4:0]; 
   logic 			       S_8_L[3:0], S_8_H[3:0];
   logic 			       E_8_L[3:0], E_8_H[3:0];

   // PPs for low 8 bits
   assign pp_8_L[0] = pp[0][8:0];
   assign pp_8_L[1] = pp[1][8:0];
   assign pp_8_L[2] = pp[2][8:0];
   assign pp_8_L[3] = pp[3][8:0];
   
   booth2_pp_gen #(8+1) mul_pp_8_L_4
     (
      .pp_out(pp_8_L[4]),
      .pp_s(),			// not need
      .pp_e(),
      .mcand(a_8_L),		// multiplicand
      .booth2({{2{b_8_L_sign}}, b[7]})
      );
   //the S for pp_8_L
   assign S_8_L[0] = S[0];
   assign S_8_L[1] = S[1];
   assign S_8_L[2] = S[2];
   assign S_8_L[3] = S[3];
   //the E for pp_8_L
   assign E_8_L[0] = E[0];
   assign E_8_L[1] = E[1];
   assign E_8_L[2] = E[2];
   assign E_8_L[3] = E[3];
   
   //PPs for high 8 bits
   assign pp_8_H[0] = pp[4][16:8];
   assign pp_8_H[1] = pp[5][16:8];
   assign pp_8_H[2] = pp[6][16:8];
   assign pp_8_H[3] = pp[7][16:8];
   assign pp_8_H[4] = pp[8][16:8];
   //S for PP_8_H
   assign S_8_H[0] = S[4];
   assign S_8_H[1] = S[5];
   assign S_8_H[2] = S[6];
   assign S_8_H[3] = S[7];
   //the E for pp_E_H
   assign E_8_H[0] = E[4];
   assign E_8_H[1] = E[5];
   assign E_8_H[2] = E[6];
   assign E_8_H[3] = E[7];


   



   logic [15:0] 		 result_16b;

   // // ==================== for simulation ====================
   // logic signed [2:0] 		 booth_array_sim[8:0]; // 0, +-1, +-2
   // logic signed [15+1:0] 	 pp_sim[8:0];
   // logic 			 S_sim[8:0];
   // logic 			 E_sim[8:0];
   logic [3:0] 			 cols_sim[31:0]; // the max column height is 9, so must use 4 bits to represent
   logic [31:0] 		 result_sim;
   logic [3:0] 			 cols_sim_16[31:0]; // for 16x16 mode
   // logic [3:0] 			 cols_sim_H[31:0];
   
   // //logic signed [15+1:0] 	 pp_actual[8:0];
   // logic signed [31:0] 		 pp_actual_sim[8:0]; // 17 bits or 32bits ????
   
      

   // // for 16-bit mode
   // // ========== generate PPs and sign compensation : S, E ==========
   // generate
   //    genvar 			 i;
   //    for(i=0;i<9;i++)
   // 	begin : mul_pps
   // 	   booth2_pp_gen #(16+1) unit // mul_pps[1].unit.xxx, the width of PP should one more than the input width
   // 	    (
   // 	     .pp_out(pp[i]),
   // 	     .pp_s(S[i]),
   // 	     .pp_e(E[i]),

   // 	     .mcand(a_mix),				// multiplicand
   // 	     .booth2(b_16_ext[i*2+2:i*2])	// booth2 code of multiplier
   // 	     );
   // 	end // block: mul_pp
   // endgenerate

   // only for 8-bit mode
   

// ==================== compress ====================
   logic [31:0] 		 final_pp0, final_pp1;
   logic [31:0] 		 result; // the real result may be a signed number 
   
   // sign compensation for mix mode
   assign C = a_8_L_sign ^ b_8_L_sign;
   
// ==================== wires need create ====================
logic S1_1_1,S1_1_0,S1_3_1,S1_4_2,S1_5_1,S1_4_1,S1_6_2,S1_7_2,S1_7_3,S1_8_2,S1_7_1,S1_9_2,S1_9_3,S1_10_3,S1_10_4,S1_11_2,S1_11_3,S1_10_2,S1_12_3,S1_12_4,S1_13_3,S1_13_4,S1_13_5,S1_14_3,S1_14_4,S1_13_2,S1_15_3,S1_15_4,S1_15_5,S1_16_3,S1_16_4,S1_16_5,S1_17_3,S1_17_4,S1_17_5,S1_18_3,S1_18_4,S1_18_5,S1_19_3,S1_19_4,S1_19_5,S1_20_3,S1_20_4,S1_20_5,S1_21_3,S1_21_4,S1_21_5,S1_22_3,S1_22_4,S1_21_2,S1_23_2,S1_23_3,S1_22_2,S1_24_2,S1_24_3,S1_25_2,S1_25_3,S1_26_2,S1_26_3,S1_27_2,S1_27_3,S1_28_2,S1_27_1,S1_29_1,S1_28_1,S1_30_1,S1_31_1,S1_31_Carry_0;
logic S2_0_0,S2_2_1,S2_2_0,S2_4_1,S2_5_1,S2_6_1,S2_7_2,S2_8_1,S2_7_1,S2_9_2,S2_10_2,S2_9_1,S2_11_2,S2_11_3,S2_12_2,S2_11_1,S2_13_2,S2_13_3,S2_14_2,S2_14_3,S2_15_2,S2_15_3,S2_16_2,S2_16_3,S2_17_2,S2_17_3,S2_18_2,S2_18_3,S2_19_2,S2_19_3,S2_20_2,S2_20_3,S2_21_2,S2_21_3,S2_22_2,S2_22_3,S2_23_2,S2_23_3,S2_24_2,S2_23_1,S2_25_2,S2_24_1,S2_26_2,S2_25_1,S2_27_2,S2_26_1,S2_28_1,S2_27_1,S2_29_1,S2_30_1,S2_31_1,S2_31_Carry_0;
logic S3_0_0,S3_1_0,S3_3_1,S3_3_0,S3_5_1,S3_6_1,S3_7_1,S3_8_1,S3_9_1,S3_10_1,S3_11_2,S3_12_1,S3_11_1,S3_13_2,S3_14_2,S3_13_1,S3_15_2,S3_14_1,S3_16_2,S3_15_1,S3_17_2,S3_16_1,S3_18_2,S3_17_1,S3_19_2,S3_18_1,S3_20_2,S3_19_1,S3_21_2,S3_20_1,S3_22_2,S3_21_1,S3_23_2,S3_22_1,S3_24_1,S3_23_1,S3_25_1,S3_26_1,S3_27_1,S3_28_1,S3_29_1,S3_30_1,S3_31_1,S3_31_Carry_0;
logic S4_0_0,S4_1_0,S4_2_0,S4_4_1,S4_4_0,S4_6_1,S4_7_1,S4_8_1,S4_9_1,S4_10_1,S4_11_1,S4_12_1,S4_13_1,S4_14_1,S4_15_1,S4_16_1,S4_17_1,S4_18_1,S4_19_1,S4_20_1,S4_21_1,S4_22_1,S4_23_1,S4_24_1,S4_25_1,S4_26_1,S4_27_1,S4_28_1,S4_29_1,S4_30_1,S4_31_1,S4_31_Carry_0;
// ==================== Stage1 ====================
HA ha1 (S1_1_1,S1_0_0,pp[0][0],S[0]);
assign S1_1_0 = pp[0][1];
FA fa1 (S1_3_1,S1_2_0,pp[1][0],pp[0][2],S[1]);
HA ha2 (S1_4_2,S1_3_0,pp[1][1],pp[0][3]);
FA fa2 (S1_5_1,S1_4_0,pp[2][0],pp[1][2],pp[0][4]);
assign S1_4_1 = S[2];
FA fa3 (S1_6_2,S1_5_0,pp[2][1],pp[1][3],pp[0][5]);
FA fa4 (S1_7_2,S1_6_0,pp[3][0],pp[2][2],pp[1][4]);
HA ha3 (S1_7_3,S1_6_1,pp[0][6],S[3]);
FA fa5 (S1_8_2,S1_7_0,pp[3][1],pp[2][3],pp[1][5]);
assign S1_7_1 = pp[0][7];
FA fa6 (S1_9_2,S1_8_0,pp[3][2],pp[2][4],pp[1][6]);
FA fa7 (S1_9_3,S1_8_1,pp[0][8],(mode8 ? pp_8_L[4][0] : pp[4][0]),(~mode8 & S[4]));
FA fa8 (S1_10_3,S1_9_0,pp[3][3],pp[2][5],pp[1][7]);
HA ha4 (S1_10_4,S1_9_1,(mode8 ? {~E[0]} : pp[4][1]),(mode8 ? pp_8_L[4][1] : pp[0][9]));
FA fa9 (S1_11_2,S1_10_0,pp[3][4],pp[2][6],pp[1][8]);
FA fa10 (S1_11_3,S1_10_1,(mode8 ? {~E[0]} : pp[5][0]),(mode8 ? pp_8_L[4][2] : pp[4][2]),(~mode8 & pp[0][10]));
assign S1_10_2 = (~mode8 & S[5]);
FA fa11 (S1_12_3,S1_11_0,pp[3][5],pp[2][7],(mode8 ? pp_8_L[4][3] : pp[5][1]));
FA fa12 (S1_12_4,S1_11_1,(mode8 ? E[1] : pp[4][3]),(mode8 ? E[0] : pp[1][9]),(~mode8 & pp[0][11]));
FA fa13 (S1_13_3,S1_12_0,pp[3][6],pp[2][8],(mode8 ? pp_8_L[4][4] : pp[6][0]));
FA fa14 (S1_13_4,S1_12_1,(mode8 ? 1'b1 : pp[5][2]),(~mode8 & pp[4][4]),(~mode8 & pp[1][10]));
HA ha5 (S1_13_5,S1_12_2,(~mode8 & pp[0][12]),(~mode8 & S[6]));
FA fa15 (S1_14_3,S1_13_0,pp[3][7],(mode8 ? pp_8_L[4][5] : pp[6][1]),(mode8 ? E[2] : pp[5][3]));
FA fa16 (S1_14_4,S1_13_1,(~mode8 & pp[4][5]),(~mode8 & pp[2][9]),(~mode8 & pp[1][11]));
assign S1_13_2 = (~mode8 & pp[0][13]);
FA fa17 (S1_15_3,S1_14_0,pp[3][8],(mode8 ? pp_8_L[4][6] : pp[7][0]),(mode8 ? 1'b1 : pp[6][2]));
FA fa18 (S1_15_4,S1_14_1,(~mode8 & pp[5][4]),(~mode8 & pp[4][6]),(~mode8 & pp[2][10]));
FA fa19 (S1_15_5,S1_14_2,(~mode8 & pp[1][12]),(~mode8 & pp[0][14]),(~mode8 & S[7]));
FA fa20 (S1_16_3,S1_15_0,(mode8 ? pp_8_L[4][7] : pp[7][1]),(mode8 ? E[3] : pp[6][3]),(~mode8 & pp[5][5]));
FA fa21 (S1_16_4,S1_15_1,(~mode8 & pp[4][7]),(~mode8 & pp[3][9]),(~mode8 & pp[2][11]));
HA ha6 (S1_16_5,S1_15_2,(~mode8 & pp[1][13]),(~mode8 & pp[0][15]));
FA fa22 (S1_17_3,S1_16_0,pp[4][8],(mode8 ? S[4] : pp[8][0]),(mode8 ? C : pp[7][2]));
FA fa23 (S1_17_4,S1_16_1,(mode8 ? 1'b1 : pp[6][4]),(~mode8 & pp[5][6]),(~mode8 & pp[3][10]));
FA fa24 (S1_17_5,S1_16_2,(~mode8 & pp[2][12]),(~mode8 & pp[1][14]),(~mode8 & pp[0][16]));
FA fa25 (S1_18_3,S1_17_0,pp[4][9],(mode8 ? 1'b1 : {~E[0]}),(~mode8 & pp[8][1]));
FA fa26 (S1_18_4,S1_17_1,(~mode8 & pp[7][3]),(~mode8 & pp[6][5]),(~mode8 & pp[5][7]));
FA fa27 (S1_18_5,S1_17_2,(~mode8 & pp[3][11]),(~mode8 & pp[2][13]),(~mode8 & pp[1][15]));
FA fa28 (S1_19_3,S1_18_0,pp[5][8],pp[4][10],(mode8 ? S[5] : {~E[0]}));
FA fa29 (S1_19_4,S1_18_1,(mode8 ? 1'b1 : pp[8][2]),(~mode8 & pp[7][4]),(~mode8 & pp[6][6]));
FA fa30 (S1_19_5,S1_18_2,(~mode8 & pp[3][12]),(~mode8 & pp[2][14]),(~mode8 & pp[1][16]));
FA fa31 (S1_20_3,S1_19_0,pp[5][9],pp[4][11],(mode8 ? 1'b1 : pp[8][3]));
FA fa32 (S1_20_4,S1_19_1,(~mode8 & pp[7][5]),(~mode8 & pp[6][7]),(~mode8 & pp[3][13]));
FA fa33 (S1_20_5,S1_19_2,(~mode8 & pp[2][15]),(~mode8 & E[1]),(~mode8 & E[0]));
FA fa34 (S1_21_3,S1_20_0,pp[6][8],pp[5][10],pp[4][12]);
FA fa35 (S1_21_4,S1_20_1,1'b1,(mode8 ? S[6] : pp[8][4]),(~mode8 & pp[7][6]));
HA ha7 (S1_21_5,S1_20_2,(~mode8 & pp[3][14]),(~mode8 & pp[2][16]));
FA fa36 (S1_22_3,S1_21_0,pp[6][9],pp[5][11],pp[4][13]);
FA fa37 (S1_22_4,S1_21_1,(mode8 ? 1'b1 : pp[8][5]),(~mode8 & pp[7][7]),(~mode8 & pp[3][15]));
assign S1_21_2 = (~mode8 & E[2]);
FA fa38 (S1_23_2,S1_22_0,pp[7][8],pp[6][10],pp[5][12]);
FA fa39 (S1_23_3,S1_22_1,pp[4][14],1'b1,(mode8 ? S[7] : pp[8][6]));
assign S1_22_2 = (~mode8 & pp[3][16]);
FA fa40 (S1_24_2,S1_23_0,pp[7][9],pp[6][11],pp[5][13]);
FA fa41 (S1_24_3,S1_23_1,pp[4][15],(mode8 ? 1'b1 : pp[8][7]),(~mode8 & E[3]));
FA fa42 (S1_25_2,S1_24_0,pp[8][8],pp[7][10],pp[6][12]);
FA fa43 (S1_25_3,S1_24_1,pp[5][14],pp[4][16],1'b1);
FA fa44 (S1_26_2,S1_25_0,pp[8][9],pp[7][11],pp[6][13]);
HA ha8 (S1_26_3,S1_25_1,pp[5][15],E[4]);
FA fa45 (S1_27_2,S1_26_0,pp[8][10],pp[7][12],pp[6][14]);
HA ha9 (S1_27_3,S1_26_1,pp[5][16],1'b1);
FA fa46 (S1_28_2,S1_27_0,pp[8][11],pp[7][13],pp[6][15]);
assign S1_27_1 = E[5];
FA fa47 (S1_29_1,S1_28_0,pp[8][12],pp[7][14],pp[6][16]);
assign S1_28_1 = 1'b1;
FA fa48 (S1_30_1,S1_29_0,pp[8][13],pp[7][15],E[6]);
FA fa49 (S1_31_1,S1_30_0,pp[8][14],pp[7][16],1'b1);
HA ha10 (S1_31_Carry_0,S1_31_0,pp[8][15],E[7]);
// ==================== Stage2 ====================
assign S2_0_0 = S1_0_0;
HA ha11 (S2_2_1,S2_1_0,S1_1_0,S1_1_1);
assign S2_2_0 = S1_2_0;
HA ha12 (S2_4_1,S2_3_0,S1_3_0,S1_3_1);
FA fa50 (S2_5_1,S2_4_0,S1_4_0,S1_4_1,S1_4_2);
HA ha13 (S2_6_1,S2_5_0,S1_5_0,S1_5_1);
FA fa51 (S2_7_2,S2_6_0,S1_6_0,S1_6_1,S1_6_2);
FA fa52 (S2_8_1,S2_7_0,S1_7_0,S1_7_1,S1_7_2);
assign S2_7_1 = S1_7_3;
FA fa53 (S2_9_2,S2_8_0,S1_8_0,S1_8_1,S1_8_2);
FA fa54 (S2_10_2,S2_9_0,S1_9_0,S1_9_1,S1_9_2);
assign S2_9_1 = S1_9_3;
FA fa55 (S2_11_2,S2_10_0,S1_10_0,S1_10_1,S1_10_2);
HA ha14 (S2_11_3,S2_10_1,S1_10_3,S1_10_4);
FA fa56 (S2_12_2,S2_11_0,S1_11_0,S1_11_1,S1_11_2);
assign S2_11_1 = S1_11_3;
FA fa57 (S2_13_2,S2_12_0,S1_12_0,S1_12_1,S1_12_2);
HA ha15 (S2_13_3,S2_12_1,S1_12_3,S1_12_4);
FA fa58 (S2_14_2,S2_13_0,S1_13_0,S1_13_1,S1_13_2);
FA fa59 (S2_14_3,S2_13_1,S1_13_3,S1_13_4,S1_13_5);
FA fa60 (S2_15_2,S2_14_0,S1_14_0,S1_14_1,S1_14_2);
HA ha16 (S2_15_3,S2_14_1,S1_14_3,S1_14_4);
FA fa61 (S2_16_2,S2_15_0,S1_15_0,S1_15_1,S1_15_2);
FA fa62 (S2_16_3,S2_15_1,S1_15_3,S1_15_4,S1_15_5);
FA fa63 (S2_17_2,S2_16_0,S1_16_0,S1_16_1,S1_16_2);
FA fa64 (S2_17_3,S2_16_1,S1_16_3,S1_16_4,S1_16_5);
FA fa65 (S2_18_2,S2_17_0,S1_17_0,S1_17_1,S1_17_2);
FA fa66 (S2_18_3,S2_17_1,S1_17_3,S1_17_4,S1_17_5);
FA fa67 (S2_19_2,S2_18_0,S1_18_0,S1_18_1,S1_18_2);
FA fa68 (S2_19_3,S2_18_1,S1_18_3,S1_18_4,S1_18_5);
FA fa69 (S2_20_2,S2_19_0,S1_19_0,S1_19_1,S1_19_2);
FA fa70 (S2_20_3,S2_19_1,S1_19_3,S1_19_4,S1_19_5);
FA fa71 (S2_21_2,S2_20_0,S1_20_0,S1_20_1,S1_20_2);
FA fa72 (S2_21_3,S2_20_1,S1_20_3,S1_20_4,S1_20_5);
FA fa73 (S2_22_2,S2_21_0,S1_21_0,S1_21_1,S1_21_2);
FA fa74 (S2_22_3,S2_21_1,S1_21_3,S1_21_4,S1_21_5);
FA fa75 (S2_23_2,S2_22_0,S1_22_0,S1_22_1,S1_22_2);
HA ha17 (S2_23_3,S2_22_1,S1_22_3,S1_22_4);
FA fa76 (S2_24_2,S2_23_0,S1_23_0,S1_23_1,S1_23_2);
assign S2_23_1 = S1_23_3;
FA fa77 (S2_25_2,S2_24_0,S1_24_0,S1_24_1,S1_24_2);
assign S2_24_1 = S1_24_3;
FA fa78 (S2_26_2,S2_25_0,S1_25_0,S1_25_1,S1_25_2);
assign S2_25_1 = S1_25_3;
FA fa79 (S2_27_2,S2_26_0,S1_26_0,S1_26_1,S1_26_2);
assign S2_26_1 = S1_26_3;
FA fa80 (S2_28_1,S2_27_0,S1_27_0,S1_27_1,S1_27_2);
assign S2_27_1 = S1_27_3;
FA fa81 (S2_29_1,S2_28_0,S1_28_0,S1_28_1,S1_28_2);
HA ha18 (S2_30_1,S2_29_0,S1_29_0,S1_29_1);
HA ha19 (S2_31_1,S2_30_0,S1_30_0,S1_30_1);
HA ha20 (S2_31_Carry_0,S2_31_0,S1_31_0,S1_31_1);
// ==================== Stage3 ====================
assign S3_0_0 = S2_0_0;
assign S3_1_0 = S2_1_0;
HA ha21 (S3_3_1,S3_2_0,S2_2_0,S2_2_1);
assign S3_3_0 = S2_3_0;
HA ha22 (S3_5_1,S3_4_0,S2_4_0,S2_4_1);
HA ha23 (S3_6_1,S3_5_0,S2_5_0,S2_5_1);
HA ha24 (S3_7_1,S3_6_0,S2_6_0,S2_6_1);
FA fa82 (S3_8_1,S3_7_0,S2_7_0,S2_7_1,S2_7_2);
HA ha25 (S3_9_1,S3_8_0,S2_8_0,S2_8_1);
FA fa83 (S3_10_1,S3_9_0,S2_9_0,S2_9_1,S2_9_2);
FA fa84 (S3_11_2,S3_10_0,S2_10_0,S2_10_1,S2_10_2);
FA fa85 (S3_12_1,S3_11_0,S2_11_0,S2_11_1,S2_11_2);
assign S3_11_1 = S2_11_3;
FA fa86 (S3_13_2,S3_12_0,S2_12_0,S2_12_1,S2_12_2);
FA fa87 (S3_14_2,S3_13_0,S2_13_0,S2_13_1,S2_13_2);
assign S3_13_1 = S2_13_3;
FA fa88 (S3_15_2,S3_14_0,S2_14_0,S2_14_1,S2_14_2);
assign S3_14_1 = S2_14_3;
FA fa89 (S3_16_2,S3_15_0,S2_15_0,S2_15_1,S2_15_2);
assign S3_15_1 = S2_15_3;
FA fa90 (S3_17_2,S3_16_0,S2_16_0,S2_16_1,S2_16_2);
assign S3_16_1 = S2_16_3;
FA fa91 (S3_18_2,S3_17_0,S2_17_0,S2_17_1,S2_17_2);
assign S3_17_1 = S2_17_3;
FA fa92 (S3_19_2,S3_18_0,S2_18_0,S2_18_1,S2_18_2);
assign S3_18_1 = S2_18_3;
FA fa93 (S3_20_2,S3_19_0,S2_19_0,S2_19_1,S2_19_2);
assign S3_19_1 = S2_19_3;
FA fa94 (S3_21_2,S3_20_0,S2_20_0,S2_20_1,S2_20_2);
assign S3_20_1 = S2_20_3;
FA fa95 (S3_22_2,S3_21_0,S2_21_0,S2_21_1,S2_21_2);
assign S3_21_1 = S2_21_3;
FA fa96 (S3_23_2,S3_22_0,S2_22_0,S2_22_1,S2_22_2);
assign S3_22_1 = S2_22_3;
FA fa97 (S3_24_1,S3_23_0,S2_23_0,S2_23_1,S2_23_2);
assign S3_23_1 = S2_23_3;
FA fa98 (S3_25_1,S3_24_0,S2_24_0,S2_24_1,S2_24_2);
FA fa99 (S3_26_1,S3_25_0,S2_25_0,S2_25_1,S2_25_2);
FA fa100 (S3_27_1,S3_26_0,S2_26_0,S2_26_1,S2_26_2);
FA fa101 (S3_28_1,S3_27_0,S2_27_0,S2_27_1,S2_27_2);
HA ha26 (S3_29_1,S3_28_0,S2_28_0,S2_28_1);
HA ha27 (S3_30_1,S3_29_0,S2_29_0,S2_29_1);
HA ha28 (S3_31_1,S3_30_0,S2_30_0,S2_30_1);
HA ha29 (S3_31_Carry_0,S3_31_0,S2_31_0,S2_31_1);
// ==================== Stage4 ====================
assign S4_0_0 = S3_0_0;
assign S4_1_0 = S3_1_0;
assign S4_2_0 = S3_2_0;
HA ha30 (S4_4_1,S4_3_0,S3_3_0,S3_3_1);
assign S4_4_0 = S3_4_0;
HA ha31 (S4_6_1,S4_5_0,S3_5_0,S3_5_1);
HA ha32 (S4_7_1,S4_6_0,S3_6_0,S3_6_1);
HA ha33 (S4_8_1,S4_7_0,S3_7_0,S3_7_1);
HA ha34 (S4_9_1,S4_8_0,S3_8_0,S3_8_1);
HA ha35 (S4_10_1,S4_9_0,S3_9_0,S3_9_1);
HA ha36 (S4_11_1,S4_10_0,S3_10_0,S3_10_1);
FA fa102 (S4_12_1,S4_11_0,S3_11_0,S3_11_1,S3_11_2);
HA ha37 (S4_13_1,S4_12_0,S3_12_0,S3_12_1);
FA fa103 (S4_14_1,S4_13_0,S3_13_0,S3_13_1,S3_13_2);
FA fa104 (S4_15_1,S4_14_0,S3_14_0,S3_14_1,S3_14_2);
FA fa105 (S4_16_1,S4_15_0,S3_15_0,S3_15_1,S3_15_2);
FA fa106 (S4_17_1,S4_16_0,S3_16_0,S3_16_1,S3_16_2);
FA fa107 (S4_18_1,S4_17_0,S3_17_0,S3_17_1,S3_17_2);
FA fa108 (S4_19_1,S4_18_0,S3_18_0,S3_18_1,S3_18_2);
FA fa109 (S4_20_1,S4_19_0,S3_19_0,S3_19_1,S3_19_2);
FA fa110 (S4_21_1,S4_20_0,S3_20_0,S3_20_1,S3_20_2);
FA fa111 (S4_22_1,S4_21_0,S3_21_0,S3_21_1,S3_21_2);
FA fa112 (S4_23_1,S4_22_0,S3_22_0,S3_22_1,S3_22_2);
FA fa113 (S4_24_1,S4_23_0,S3_23_0,S3_23_1,S3_23_2);
HA ha38 (S4_25_1,S4_24_0,S3_24_0,S3_24_1);
HA ha39 (S4_26_1,S4_25_0,S3_25_0,S3_25_1);
HA ha40 (S4_27_1,S4_26_0,S3_26_0,S3_26_1);
HA ha41 (S4_28_1,S4_27_0,S3_27_0,S3_27_1);
HA ha42 (S4_29_1,S4_28_0,S3_28_0,S3_28_1);
HA ha43 (S4_30_1,S4_29_0,S3_29_0,S3_29_1);
HA ha44 (S4_31_1,S4_30_0,S3_30_0,S3_30_1);
HA ha45 (S4_31_Carry_0,S4_31_0,S3_31_0,S3_31_1);
// ==================== Final 2 PPs ====================
assign final_pp0 = {S4_31_0,S4_30_0,S4_29_0,S4_28_0,S4_27_0,S4_26_0,S4_25_0,S4_24_0,S4_23_0,S4_22_0,S4_21_0,S4_20_0,S4_19_0,S4_18_0,S4_17_0,S4_16_0,S4_15_0,S4_14_0,S4_13_0,S4_12_0,S4_11_0,S4_10_0,S4_9_0,S4_8_0,S4_7_0,S4_6_0,S4_5_0,S4_4_0,S4_3_0,S4_2_0,S4_1_0,S4_0_0};
assign final_pp1 = {S4_31_1,S4_30_1,S4_29_1,S4_28_1,S4_27_1,S4_26_1,S4_25_1,S4_24_1,S4_23_1,S4_22_1,S4_21_1,S4_20_1,S4_19_1,S4_18_1,S4_17_1,S4_16_1,S4_15_1,S4_14_1,S4_13_1,S4_12_1,S4_11_1,S4_10_1,S4_9_1,S4_8_1,S4_7_1,S4_6_1,1'b0,S4_4_1,1'b0,1'b0,1'b0,1'b0};

// -------------------- total 113 FAs and 45 HAs --------------------
   
   // ==================== the final CPA ====================
   assign o_result = final_pp0 + final_pp1;
   
   

   initial begin
      #10;
      
      for(int i=0;i<=8;i++)
	begin
	   $display("pp[%d] = %x", i, pp[i]);
	end
      
      for(int i=0;i<=7;i++)
	begin
	   $display("S[%d] = %d, E[%d] = %d", i, S[i], i, E[i]);
	end
      
      
      // calc each column
      cols_sim[0] = pp[0][0] + S[0];
      cols_sim[1] = pp[0][1];
      cols_sim[2] = pp[1][0] + pp[0][2] + S[1];
      cols_sim[3] = pp[1][1] + pp[0][3];
      cols_sim[4] = pp[2][0] + pp[1][2] + pp[0][4] + S[2];
      cols_sim[5] = pp[2][1] + pp[1][3] + pp[0][5];
      cols_sim[6] = pp[3][0] + pp[2][2] + pp[1][4] + pp[0][6] + S[3];
      cols_sim[7] = pp[3][1] + pp[2][3] + pp[1][5] + pp[0][7];
      cols_sim[8] = pp[3][2] + pp[2][4] + pp[1][6] + pp[0][8] + (mode8 ? pp_8_L[4][0] : pp[4][0]) + (~mode8 & S[4]);
      cols_sim[9] = pp[3][3] + pp[2][5] + pp[1][7] + (mode8 ? {~E[0]} : pp[4][1]) + (mode8 ? pp_8_L[4][1] : pp[0][9]);
      cols_sim[10] = pp[3][4] + pp[2][6] + pp[1][8] + (mode8 ? {~E[0]} : pp[5][0]) + (mode8 ? pp_8_L[4][2] : pp[4][2]) + (~mode8 & pp[0][10]) + (~mode8 & S[5]);
      cols_sim[11] = pp[3][5] + pp[2][7] + (mode8 ? pp_8_L[4][3] : pp[5][1]) + (mode8 ? E[1] : pp[4][3]) + (mode8 ? E[0] : pp[1][9]) + (~mode8 & pp[0][11]);
      cols_sim[12] = pp[3][6] + pp[2][8] + (mode8 ? pp_8_L[4][4] : pp[6][0]) + (mode8 ? 1 : pp[5][2]) + (~mode8 & pp[4][4]) + (~mode8 & pp[1][10]) + (~mode8 & pp[0][12]) + (~mode8 & S[6]);
      cols_sim[13] = pp[3][7] + (mode8 ? pp_8_L[4][5] : pp[6][1]) + (mode8 ? E[2] : pp[5][3]) + (~mode8 & pp[4][5]) + (~mode8 & pp[2][9]) + (~mode8 & pp[1][11]) + (~mode8 & pp[0][13]);
      cols_sim[14] = pp[3][8] + (mode8 ? pp_8_L[4][6] : pp[7][0]) + (mode8 ? 1 : pp[6][2]) + (~mode8 & pp[5][4]) + (~mode8 & pp[4][6]) + (~mode8 & pp[2][10]) + (~mode8 & pp[1][12]) + (~mode8 & pp[0][14]) + (~mode8 & S[7]);
      cols_sim[15] = (mode8 ? pp_8_L[4][7] : pp[7][1]) + (mode8 ? E[3] : pp[6][3]) + (~mode8 & pp[5][5]) + (~mode8 & pp[4][7]) + (~mode8 & pp[3][9]) + (~mode8 & pp[2][11]) + (~mode8 & pp[1][13]) + (~mode8 & pp[0][15]);
      cols_sim[16] = pp[4][8] + (mode8 ? S[4] : pp[8][0]) + (mode8 ? C : pp[7][2]) + (mode8 ? 1 : pp[6][4]) + (~mode8 & pp[5][6]) + (~mode8 & pp[3][10]) + (~mode8 & pp[2][12]) + (~mode8 & pp[1][14]) + (~mode8 & pp[0][16]);
      cols_sim[17] = pp[4][9] + (mode8 ? 1 : {~E[0]}) + (~mode8 & pp[8][1]) + (~mode8 & pp[7][3]) + (~mode8 & pp[6][5]) + (~mode8 & pp[5][7]) + (~mode8 & pp[3][11]) + (~mode8 & pp[2][13]) + (~mode8 & pp[1][15]);
      cols_sim[18] = pp[5][8] + pp[4][10] + (mode8 ? S[5] : {~E[0]}) + (mode8 ? 1 : pp[8][2]) + (~mode8 & pp[7][4]) + (~mode8 & pp[6][6]) + (~mode8 & pp[3][12]) + (~mode8 & pp[2][14]) + (~mode8 & pp[1][16]);
      cols_sim[19] = pp[5][9] + pp[4][11] + (mode8 ? 1 : pp[8][3]) + (~mode8 & pp[7][5]) + (~mode8 & pp[6][7]) + (~mode8 & pp[3][13]) + (~mode8 & pp[2][15]) + (~mode8 & E[1]) + (~mode8 & E[0]);
      cols_sim[20] = pp[6][8] + pp[5][10] + pp[4][12] + 1'b1 + (mode8 ? S[6] : pp[8][4]) + (~mode8 & pp[7][6]) + (~mode8 & pp[3][14]) + (~mode8 & pp[2][16]);
      cols_sim[21] = pp[6][9] + pp[5][11] + pp[4][13] + (mode8 ? 1 : pp[8][5]) + (~mode8 & pp[7][7]) + (~mode8 & pp[3][15]) + (~mode8 & E[2]);
      cols_sim[22] = pp[7][8] + pp[6][10] + pp[5][12] + pp[4][14] + 1'b1 + (mode8 ? S[7] : pp[8][6]) + (~mode8 & pp[3][16]);
      cols_sim[23] = pp[7][9] + pp[6][11] + pp[5][13] + pp[4][15] + (mode8 ? 1 : pp[8][7]) + (~mode8 & E[3]);
      cols_sim[24] = pp[8][8] + pp[7][10] + pp[6][12] + pp[5][14] + pp[4][16] + 1'b1;
      cols_sim[25] = pp[8][9] + pp[7][11] + pp[6][13] + pp[5][15] + E[4];
      cols_sim[26] = pp[8][10] + pp[7][12] + pp[6][14] + pp[5][16] + 1'b1;
      cols_sim[27] = pp[8][11] + pp[7][13] + pp[6][15] + E[5];
      cols_sim[28] = pp[8][12] + pp[7][14] + pp[6][16] + 1'b1;
      cols_sim[29] = pp[8][13] + pp[7][15] + E[6];
      cols_sim[30] = pp[8][14] + pp[7][16] + 1'b1;
      cols_sim[31] = pp[8][15] + E[7];
      
      



      if(mode8 == 1'b0)
	begin : verify_pps_16x16
      	   pps_16x16_t pps_16;
      	   pps_16 = gen_16x16_pps(
      				  .i_a(16'habcd),
      				  .i_b(16'h5678),
      				  .i_sign(1'b1)
      				  );
	   $display("==================== verify PP, S, E for 16x16 mode ====================");
	   for(int i=0;i<9;i++)
	     $display("pp_16[%d] = %x  <==>  pps_16.pp[%d] = %x    => %s", i, pp_16[i], i, pps_16.pp[i], (pp_16[i]==pps_16.pp[i] ? "equal" : "!!! not equal !!!"));
	   for(int i=0;i<8;i++)
	     $display("S_16[%d] = %x  <==>  pps_16.S[%d] = %x    => %s", i, S_16[i], i, pps_16.S[i], (S_16[i]==pps_16.S[i] ? "equal" : "!!! not equal !!!"));
	   for(int i=0;i<8;i++)
	     $display("E_16[%d] = %x  <==>  pps_16.E[%d] = %x    => %s", i, E_16[i], i, pps_16.E[i], (E_16[i]==pps_16.E[i] ? "equal" : "!!! not equal !!!"));
	 
	   // for(int i=0;i<=31;i++)
	   //   $display("cols_sim[%d] = %d  <==> pps_16.cols_sum[%d] = %d   =>  %s", i, cols_sim[i], i, pps_16.cols_sum[i], (cols_sim[i]==pps_16.cols_sum[i] ? "equal" : "!!! not equal !!!"));
	end // block: verify_pps_16x16
      else
	begin : verify_pps_8x8
	   pps_8x8_t pps_8_L;
	   pps_8x8_t pps_8_H;
	   
      	   pps_8_L = gen_8x8_pps(
      				 .i_a(8'hcd),
      				 .i_b(8'h78),
      				 .i_sign(1'b1)
      				 );
      	   pps_8_H = gen_8x8_pps(
      				 .i_a(8'hab),
      				 .i_b(8'h56),
      				 .i_sign(1'b1)
      				 );

	   $display("==================== verify PP, S, E for low 8 bits ====================");
	   for(int i=0;i<5;i++)
	     $display("pp_8_L[%d] = %x  <==>  pps_8_L.pp[%d] = %x    => %s", i, pp_8_L[i], i, pps_8_L.pp[i], (pp_8_L[i]==pps_8_L.pp[i] ? "equal" : "!!! not equal !!!"));
	   for(int i=0;i<4;i++)
	     $display("S_8_L[%d] = %x  <==>  pps_8_L.S[%d] = %x    => %s", i, S_8_L[i], i, pps_8_L.S[i], S_8_L[i]==pps_8_L.S[i] ? "equal" : "!!! not equal !!!");
	   for(int i=0;i<4;i++)
	     $display("E_8_L[%d] = %x  <==>  pps_8_L.E[%d] = %x    => %s", i, E_8_L[i], i, pps_8_L.E[i], E_8_L[i]==pps_8_L.E[i] ? "equal" : "!!! not equal !!!");

	   $display("==================== verify PP, S, E for high 8 bits ====================");
	   for(int i=0;i<5;i++)
	     $display("pp_8_H[%d] = %x  <==>  pps_8_H.pp[%d] = %x    => %s", i, pp_8_H[i], i, pps_8_H.pp[i], pp_8_H[i]==pps_8_H.pp[i] ? "equal" : "!!! not equal !!!");
	   for(int i=0;i<4;i++)
	     $display("S_8_H[%d] = %x  <==>  pps_8_H.S[%d] = %x    => %s", i, S_8_H[i], i, pps_8_H.S[i], S_8_H[i]==pps_8_H.S[i] ? "equal" : "!!! not equal !!!");
	   for(int i=0;i<4;i++)
	     $display("E_8_H[%d] = %x  <==>  pps_8_H.E[%d] = %x    => %s", i, E_8_H[i], i, pps_8_H.E[i], E_8_H[i]==pps_8_H.E[i] ? "equal" : "!!! not equal !!!");

	end
      
      // calc the columns' value only in 16x16 mode ( no useful in 8x8 mode)
      // begin : verify_cols_sum
      // 	 pps_16x16_t pps_16;
      // 	 pps_16 = gen_16x16_pps(
      // 				.i_a(16'habcd),
      // 				.i_b(16'h5678),
      // 				.i_sign(1'b1)
      // 				);

      // 	 for(int i=0;i<=31;i++)
      // 	   $display("cols_sim_16[%d] : %x   <===> pps_16.cols_sum[%d] : %x   =>  %s", i, cols_sim_16[i], i, pps_16.cols_sum[i], cols_sim_16[i]==pps_16.cols_sum[i] ? "equal" : "!!!! not equal !!!!");
      
      // end
	 

      //get the result
      result_sim = 32'd0;
      for(int i=0;i<32;i++)
	result_sim += cols_sim[i]<<i;
      $display("result_sim is %d(%x)", $signed(result_sim), result_sim);
      
      
      //get the result
      result_sim = 32'd0;
      for(int i=0;i<32;i++)
	result_sim += cols_sim_16[i]<<i;
      $display("result_sim is %d(%x)", $signed(result_sim), result_sim);



      $display("o_result = %x", o_result);


   end



   
   

   // logic signed [31:0] correct_result;
   // logic signed [31:0] tmp_result;

   // bit 		       flag;
   // initial begin
   //    #10
   // 	// $display("========== multiply : %d * %d", $signed(a_16), $signed(b_16));
   // 	$display("========== multiply : %d * %d", $signed(a_8_L), $signed(b_8_L));
      

   //    // ==================== for simulation ====================
   //    //booth2 recoding 
   //    for(int i=0;i<=16;i+=2)	// total 9
   // 	begin
   // 	   booth_array_sim[i/2] = b_16_ext[i] + b_16_ext[i+1] - 2*b_16_ext[i+2]; // 0,+-1,+-2
   // 	   $display("booth_array[%d] = %d", i/2, booth_array_sim[i/2]);
   // 	end
   //    //gen actual value of PPs for verify
   //    for(int i=0;i<=8;i++)
   // 	begin
   // 	   pp_actual_sim[i] = $signed(a_16) * booth_array_sim[i];
   // 	   $display("actual PP[%d] = %d(%x)", i, pp_actual_sim[i], pp_actual_sim[i]);
   // 	end
   //    tmp_result = 0;
   //    for(int i=0;i<=8;i++)
   // 	tmp_result += pp_actual_sim[i]<<(i*2); // remember the shift
   //    $display("========== the sum of actual PPs is %d(%x)", tmp_result, tmp_result);
      
   //    // gen PPs and S, E
   //    for(int i=0;i<=8;i++)
   // 	begin
   // 	   case(booth_array_sim[i])
   // 	     3'd0:
   // 	       begin
   // 		  pp_sim[i] = '0;
   // 	       end
   // 	     3'd1:
   // 	       pp_sim[i] = a_16;
   // 	     3'd2:
   // 	       pp_sim[i] = a_16<<1;
   // 	     -3'd1:
   // 	       pp_sim[i] = ~a_16;
   // 	     -3'd2:
   // 	       pp_sim[i] = ~(a_16<<1);
   // 	   endcase // case (booth_array_sim[i])
   // 	   //S (the same as the sign of booth_array_sim[i])
   // 	   if(booth_array_sim[i] < 0)
   // 	     S_sim[i] = 1'b1;
   // 	   else
   // 	     S_sim[i] = 1'b0;
   // 	   //E
   // 	   E_sim[i] = (booth_array_sim[i] == 3'd0) ? 1'b1 : S_sim[i] ~^ a_16[16];
   // 	end // for (int i=0;i<=8;i++)


   //    flag = 1;
   //    $display("check the correctness of all PPs");
   //    for(int i=0;i<=8;i++)
   // 	begin
   // 	   flag &= (pp[i] == pp_sim[i]);
   // 	   $display("pp[%d]=%x\tpp_sim[%d]=%x  => %s", i, pp[i], i, pp_sim[i], pp[i]==pp_sim[i] ? "equal" : "!!! not equal !!!");
   // 	end
   //    if(flag)
   // 	$display("========== all PPs are correct");
   //    else
   // 	$display("*E: some PPs are error !");

   //    flag = 1;
   //    for(int i=0;i<=8;i++)
   // 	begin
   // 	   flag &= (S[i] == S_sim[i]);
   // 	   $display("S[%d]=%d\tS_sim[%d]=%d  => %s", i, S[i], i, S_sim[i], S[i]==S_sim[i] ? "equal" : "!!! not equal !!!");
   // 	end
   //    if(flag)
   // 	$display("========== all S are correct");
   //    else
   // 	$display("*E: some S are error !");

   //    flag = 1;
   //    for(int i=0;i<=8;i++)
   // 	begin
   // 	   flag &= (E[i] == E_sim[i]);
   // 	   $display("E[%d]=%d\tE_sim[%d]=%d  => %s", i, E[i], i, E_sim[i], E[i]==E_sim[i] ? "equal" : "!!! not equal !!!");
   // 	end
   //    if(flag)
   // 	$display("========== all E are correct");
   //    else
   // 	$display("*E: some E are error !");




   //    for(int i=0;i<=4;i++)
   // 	$display("pp_8_L[%d] = 0x%x", i, pp_8_L[i]);

   //    for(int i=0;i<4;i++)
   // 	$display("S_8_L[%d] = %d, E_8_L[%d] = %d", i, S_8_L[i], i, E_8_L[i]);
	  
	  
   //    cols_sim[0] = pp_8_L[0][0] + S_8_L[0];
   //    cols_sim[1] = pp_8_L[0][1];
   //    cols_sim[2] = pp_8_L[0][2] + pp_8_L[1][0] + S_8_L[1];
   //    cols_sim[3] = pp_8_L[0][3] + pp_8_L[1][1];
   //    cols_sim[4] = pp_8_L[0][4] + pp_8_L[1][2] + pp_8_L[2][0] + S_8_L[2];
   //    cols_sim[5] = pp_8_L[0][5] + pp_8_L[1][3] + pp_8_L[2][1];
   //    cols_sim[6] = pp_8_L[0][6] + pp_8_L[1][4] + pp_8_L[2][2] + pp_8_L[3][0] + S_8_L[3];
   //    cols_sim[7] = pp_8_L[0][7] + pp_8_L[1][5] + pp_8_L[2][3] + pp_8_L[3][1];
   //    cols_sim[8] = pp_8_L[0][8] + pp_8_L[1][6] + pp_8_L[2][4] + pp_8_L[3][2] + pp_8_L[4][0];
   //    cols_sim[9] = {~E_8_L[0]} + pp_8_L[1][7] + pp_8_L[2][5] + pp_8_L[3][3] + pp_8_L[4][1];
   //    cols_sim[10] = {~E_8_L[0]} + pp_8_L[1][8] + pp_8_L[2][6] + pp_8_L[3][4] + pp_8_L[4][2];
   //    cols_sim[11] = E_8_L[0] + E_8_L[1] + pp_8_L[2][7] + pp_8_L[3][5] + pp_8_L[4][3];
   //    cols_sim[12] = 1'b1 + pp_8_L[2][8] + pp_8_L[3][6] + pp_8_L[4][4];
   //    cols_sim[13] = E_8_L[2] + pp_8_L[3][7] + pp_8_L[4][5];
   //    cols_sim[14] = 1'b1 + pp_8_L[3][8] + pp_8_L[4][6];
   //    cols_sim[15] = E_8_L[3] + pp_8_L[4][7];


   //    // result_16b = 0;
   //    // for(int i=0;i<=15;i++)
   // 	  // 	begin
   // 	  // 	   result_16b += cols_sim[i]<<i;
   // 	  // 	end
   //    // $display("after compress(8-bit mode) result = %d (%x)", $signed(result_16b), result_16b);

   //    //calc the 8x8 result when in 32 mode
   //    for(int i=16;i<32;i++)
   //    	cols_sim[i] = 1;		// must add a 11...11,00...00 (16 ones in the high 16 bits)
   //    result = 0;
   //    for(int i=0;i<32;i++)
   //    	result += cols_sim[i]<<i;
   //    $display("after compress(8-bit mode, low 8 bits) result = %d (%x)", $signed(result), result);



	
	


   //    for(int i=0;i<=4;i++)
   // 	$display("pp_8_H[%d] = 0x%x", i, pp_8_H[i]);

   //    for(int i=0;i<4;i++)
   // 	$display("S_8_H[%d] = %d, E_8_H[%d] = %d", i, S_8_H[i], i, E_8_H[i]);

      
   //    for(int i=0;i<=15;i++)
   // 	cols_sim_H[i] = 0;
   //    cols_sim_H[16] = pp_8_H[0][0] + S_8_H[0];
   //    cols_sim_H[17] = pp_8_H[0][1];
   //    cols_sim_H[18] = pp_8_H[0][2] + pp_8_H[1][0] + S_8_H[1];
   //    cols_sim_H[19] = pp_8_H[0][3] + pp_8_H[1][1];
   //    cols_sim_H[20] = pp_8_H[0][4] + pp_8_H[1][2] + pp_8_H[2][0] + S_8_H[2];
   //    cols_sim_H[21] = pp_8_H[0][5] + pp_8_H[1][3] + pp_8_H[2][1];
   //    cols_sim_H[22] = pp_8_H[0][6] + pp_8_H[1][4] + pp_8_H[2][2] + pp_8_H[3][0] + S_8_H[3];
   //    cols_sim_H[23] = pp_8_H[0][7] + pp_8_H[1][5] + pp_8_H[2][3] + pp_8_H[3][1];
   //    cols_sim_H[24] = pp_8_H[0][8] + pp_8_H[1][6] + pp_8_H[2][4] + pp_8_H[3][2] + pp_8_H[4][0];
   //    cols_sim_H[25] = {~E_8_H[0]} + pp_8_H[1][7] + pp_8_H[2][5] + pp_8_H[3][3] + pp_8_H[4][1];
   //    cols_sim_H[26] = {~E_8_H[0]} + pp_8_H[1][8] + pp_8_H[2][6] + pp_8_H[3][4] + pp_8_H[4][2];
   //    cols_sim_H[27] = E_8_H[0] + E_8_H[1] + pp_8_H[2][7] + pp_8_H[3][5] + pp_8_H[4][3];
   //    cols_sim_H[28] = 1'b1 + pp_8_H[2][8] + pp_8_H[3][6] + pp_8_H[4][4];
   //    cols_sim_H[29] = E_8_H[2] + pp_8_H[3][7] + pp_8_H[4][5];
   //    cols_sim_H[30] = 1'b1 + pp_8_H[3][8] + pp_8_H[4][6];
   //    cols_sim_H[31] = E_8_H[3] + pp_8_H[4][7];

   //    result = 0;
   //    for(int i=0;i<32;i++)
   // 	result += cols_sim_H[i]<<i;
   //    $display("after compress(8-bit mode, high 8 bits) result = %d (%x)", $signed(result[31:16]), result);




   //    $display("calc the two 8x8 result simultaneously");
   //    for(int i=16;i<32;i++)
   // 	cols_sim[i] = cols_sim_H[i] + 1;

   //    // notice: for signed number, must add low 16-bit num's sign bit(the sign of u0*v0) to bit16 !!!!
   //    cols_sim[16] += a_8_L[8] ^ b_8_L[8];
      
      
   //    result = 0;
   //    for(int i=0;i<32;i++)
   // 	result += cols_sim[i]<<i;
   //    $display("after compress simultaneously, result = %d (%x)", $signed(result), result);
      
      

      
   //    // $display("a_sign_mix_0 = %d", a_sign_mix_0);
   //    // $display("a_mix_0[15:0] = %x", a_mix_0[15:0]);
   //    // $display("b_16_ext[4:2] = %x", b_16_ext[4:2]);
   //    // $display("pp[1] = %x", pp[1]);
   //    // $display("S[1] = %d", S[1]);
   //    // $display("E[1] = %d", E[1]);
	  
   //    $finish;
      
      




      
   //    // add each column
   //    cols_sim[0] = pp_sim[0][0] + S_sim[0];
   //    cols_sim[1] = pp_sim[0][1];
   //    cols_sim[2] = pp_sim[0][2] + pp_sim[1][0] + S_sim[1];
   //    cols_sim[3] = pp_sim[0][3] + pp_sim[1][1];
   //    cols_sim[4] = pp_sim[0][4] + pp_sim[1][2] + pp_sim[2][0] + S_sim[2];
   //    cols_sim[5] = pp_sim[0][5] + pp_sim[1][3] + pp_sim[2][1];
   //    cols_sim[6] = pp_sim[0][6] + pp_sim[1][4] + pp_sim[2][2] + pp_sim[3][0] + S_sim[3];
   //    cols_sim[7] = pp_sim[0][7] + pp_sim[1][5] + pp_sim[2][3] + pp_sim[3][1];
   //    cols_sim[8] = pp_sim[0][8] + pp_sim[1][6] + pp_sim[2][4] + pp_sim[3][2] + pp_sim[4][0] + S_sim[4];
   //    cols_sim[9] = pp_sim[0][9] + pp_sim[1][7] + pp_sim[2][5] + pp_sim[3][3] + pp_sim[4][1];
   //    cols_sim[10] = pp_sim[0][10] + pp_sim[1][8] + pp_sim[2][6] + pp_sim[3][4] + pp_sim[4][2] + pp_sim[5][0] + S_sim[5];
   //    cols_sim[11] = pp_sim[0][11] + pp_sim[1][9] + pp_sim[2][7] + pp_sim[3][5] + pp_sim[4][3] + pp_sim[5][1];
   //    cols_sim[12] = pp_sim[0][12] + pp_sim[1][10] + pp_sim[2][8] + pp_sim[3][6] + pp_sim[4][4] + pp_sim[5][2] + pp_sim[6][0] + S_sim[6];
   //    cols_sim[13] = pp_sim[0][13] + pp_sim[1][11] + pp_sim[2][9] + pp_sim[3][7] + pp_sim[4][5] + pp_sim[5][3] + pp_sim[6][1];
   //    cols_sim[14] = pp_sim[0][14] + pp_sim[1][12] + pp_sim[2][10] + pp_sim[3][8] + pp_sim[4][6] + pp_sim[5][4] + pp_sim[6][2] + pp_sim[7][0] + S_sim[7];
   //    cols_sim[15] = pp_sim[0][15] + pp_sim[1][13] + pp_sim[2][11] + pp_sim[3][9] + pp_sim[4][7] + pp_sim[5][5] + pp_sim[6][3] + pp_sim[7][1];
   //    cols_sim[16] = pp_sim[0][16] + pp_sim[1][14] + pp_sim[2][12] + pp_sim[3][10] + pp_sim[4][8] + pp_sim[5][6] + pp_sim[6][4] + pp_sim[7][2] + pp_sim[8][0];
   //    cols_sim[17] = {~E_sim[0]} + pp_sim[1][15] + pp_sim[2][13] + pp_sim[3][11] + pp_sim[4][9] + pp_sim[5][7] + pp_sim[6][5] + pp_sim[7][3] + pp_sim[8][1];
   //    cols_sim[18] = {~E_sim[0]} + pp_sim[1][16] + pp_sim[2][14] + pp_sim[3][12] + pp_sim[4][10] + pp_sim[5][8] + pp_sim[6][6] + pp_sim[7][4] + pp_sim[8][2];
   //    cols_sim[19] = E_sim[0] + E_sim[1] + pp_sim[2][15] + pp_sim[3][13] + pp_sim[4][11] + pp_sim[5][9] + pp_sim[6][7] + pp_sim[7][5] + pp_sim[8][3];
   //    cols_sim[20] = 1 + pp_sim[2][16] + pp_sim[3][14] + pp_sim[4][12] + pp_sim[5][10] + pp_sim[6][8] + pp_sim[7][6] + pp_sim[8][4];
   //    cols_sim[21] = E_sim[2] + pp_sim[3][15] + pp_sim[4][13] + pp_sim[5][11] + pp_sim[6][9] + pp_sim[7][7] + pp_sim[8][5];
   //    cols_sim[22] = 1 + pp_sim[3][16] + pp_sim[4][14] + pp_sim[5][12] + pp_sim[6][10] + pp_sim[7][8] + pp_sim[8][6];
   //    cols_sim[23] = E_sim[3] + pp_sim[4][15] + pp_sim[5][13] + pp_sim[6][11] + pp_sim[7][9] + pp_sim[8][7];
   //    cols_sim[24] = 1 + pp_sim[4][16] + pp_sim[5][14] + pp_sim[6][12] + pp_sim[7][10] + pp_sim[8][8];
   //    cols_sim[25] = E_sim[4] + pp_sim[5][15] + pp_sim[6][13] + pp_sim[7][11] + pp_sim[8][9];
   //    cols_sim[26] = 1 + pp_sim[5][16] + pp_sim[6][14] + pp_sim[7][12] + pp_sim[8][10];
   //    cols_sim[27] = E_sim[5] + pp_sim[6][15] + pp_sim[7][13] + pp_sim[8][11];
   //    cols_sim[28] = 1 + pp_sim[6][16] + pp_sim[7][14] + pp_sim[8][12];
   //    cols_sim[29] = E_sim[6] + pp_sim[7][15] + pp_sim[8][13];
   //    cols_sim[30] = 1 + pp_sim[7][16] + pp_sim[8][14];
   //    cols_sim[31] = E_sim[7] + pp_sim[8][15];
      
   //    for(int i=0;i<=31;i++)
   // 	$display("cols_sim[%d] = %d", i, cols_sim[i]);
      
   //    result = 0;
   //    for(int i=0;i<=31;i++)
   // 	begin
   // 	   result += cols_sim[i]<<i;
   // 	end
   //    $display("after compress result = %d (%x)", $signed(result), result);
      

   //    result = 0;
   //    result += final_pp0;
   //    result += final_pp1;
   //    $display("after wallace compress, result = %d (%x)", $signed(result), result);
      
  
   //    // #20
   //    // 	$display("a*b = %d * %d", $signed(a_16), $signed(b_16));
   //    // result = 0;
   // 	  // for(int i=0;i<9;i++)
   //    // 	begin
   // 	  // 	   result += pp[i]<<(i*2); // must add the S and E ???
   // 	  // 	   $display("pp[%d] = %x, S[%d] = %d, E[%d] = %d", i, pp[i], i, S[i], i, E[i]);
   // 	  // 	end
   // 	  // $display("result : %x(%d)", result, $signed(result));

   // 	  // correct_result = $signed(a_16)*$signed(b_16);
   // 	  // $display("correct result : %x(%d)", correct_result, correct_result);
   // 	  // if(result == correct_result)
   // 	  // 	$display("========== result correct ==========");
   // 	  // else
   // 	  // 	$display("========== result error ==========");
   // end
   

endmodule // booth2_mix

